package com.luo.ai.assistant.chat.memory;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Optional;

/**
 * Redis ChatMemory配置
 *
 * @author luohq
 * @date 2025-02-12 15:30
 */
@ConfigurationProperties(prefix = MyRedisMemoryConfig.PREFIX)
public class MyRedisMemoryConfig {

    public static final String PREFIX = "spring.ai.chat.memory.redis";
    /**
     * Redis Key前缀（默认"spring:ai:chat:memory:"）
     */
    private String keyPrefix = "spring:ai:chat:memory:";
    /**
     * Redis Key过期时间（秒）
     */
    private Integer timeToLiveSeconds = null;
    /**
     * 自动执行过期消息清理任务的cron表达式（0/20 0 * * * ?）
     */
    private String clearTaskCron = "0/20 * * * * ?";

    /**
     * 单次扫描清理的最大会话数（默认100）
     */
    private Integer maxConvCountPerClearScan = 100;

    /**
     * 本地缓存最大会话数（默认2000）
     */
    private Integer maxConvCountLocalCache = 2000;

    public MyRedisMemoryConfig() {
    }

    public MyRedisMemoryConfig(String keyPrefix, Integer timeToLiveSeconds, String clearTaskCron, Integer maxConvCountPerClearScan, Integer maxConvCountLocalCache) {
        this.keyPrefix = keyPrefix;
        this.timeToLiveSeconds = timeToLiveSeconds;
        this.clearTaskCron = clearTaskCron;
        this.maxConvCountPerClearScan = maxConvCountPerClearScan;
        this.maxConvCountLocalCache = maxConvCountLocalCache;
    }

    public String getKeyPrefix() {
        return keyPrefix;
    }

    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }

    public Integer getTimeToLiveSeconds() {
        return timeToLiveSeconds;
    }

    /**
     * 根具timeToLiveSeconds配置获取过期时间点（该时间点之前的消息均已过期）
     *
     * @return 过期时间点（该时间点之前的消息均已过期）
     */
    public Long getExpiredTimestampMills() {
        //过期时间点（该时间点之前的消息均已过期）
        Long expireTimeMills = Optional.ofNullable(this.timeToLiveSeconds)
                .filter(timeToLiveSeconds -> 0 < timeToLiveSeconds)
                .map(timeToLiveSeconds -> System.currentTimeMillis() - timeToLiveSeconds * 1000)
                .orElse(-1L);
        return expireTimeMills;
    }

    public void setTimeToLiveSeconds(Integer timeToLiveSeconds) {
        this.timeToLiveSeconds = timeToLiveSeconds;
    }

    public String getClearTaskCron() {
        return clearTaskCron;
    }

    public void setClearTaskCron(String clearTaskCron) {
        this.clearTaskCron = clearTaskCron;
    }

    public Integer getMaxConvCountPerClearScan() {
        return maxConvCountPerClearScan;
    }

    public void setMaxConvCountPerClearScan(Integer maxConvCountPerClearScan) {
        this.maxConvCountPerClearScan = maxConvCountPerClearScan;
    }

    public Integer getMaxConvCountLocalCache() {
        return maxConvCountLocalCache;
    }

    public void setMaxConvCountLocalCache(Integer maxConvCountLocalCache) {
        this.maxConvCountLocalCache = maxConvCountLocalCache;
    }

    @Override
    public String toString() {
        return "MyRedisMemoryConfig{" +
                "keyPrefix='" + keyPrefix + '\'' +
                ", timeToLiveSeconds=" + timeToLiveSeconds +
                ", clearTaskCron='" + clearTaskCron + '\'' +
                ", maxConvCountPerClearScan=" + maxConvCountPerClearScan +
                ", maxConvCountLocalCache=" + maxConvCountLocalCache +
                '}';
    }

    public static Builder builder() {
        return new Builder();
    }


    public static final class Builder {
        /**
         * Redis Key前缀（默认"spring:ai:chat:memory:"）
         */
        private String keyPrefix = "spring:ai:chat:memory:";
        /**
         * Redis Key过期时间（秒）
         */
        private Integer timeToLiveSeconds = null;
        /**
         * 自动执行过期消息清理任务的cron表达式（0/20 0 * * * ?）
         */
        private String clearTaskCron = "0/20 0 * * * ?";

        /**
         * 单次扫描清理的最大会话数（默认100）
         */
        private Integer maxConvCountPerClearScan = 100;

        /**
         * 本地缓存最大会话数（默认2000），<br/>
         * V2版本专有配置
         */
        private Integer maxConvCountLocalCache = 2000;


        private Builder() {
        }

        public Builder keyPrefix(String keyPrefix) {
            this.keyPrefix = keyPrefix;
            return this;
        }

        public Builder timeToLiveSeconds(Integer timeToLiveSeconds) {
            this.timeToLiveSeconds = timeToLiveSeconds;
            return this;
        }

        public Builder clearTaskCron(String clearTaskCron) {
            this.clearTaskCron = clearTaskCron;
            return this;
        }

        public Builder maxConvCountPerClearScan(Integer maxConvCountPerClearScan) {
            this.maxConvCountPerClearScan = maxConvCountPerClearScan;
            return this;
        }

        public Builder maxConvCountLocalCache(Integer maxConvCountLocalCache) {
            this.maxConvCountLocalCache = maxConvCountLocalCache;
            return this;
        }

        public MyRedisMemoryConfig build() {
            MyRedisMemoryConfig myRedisMemoryConfig = new MyRedisMemoryConfig();
            myRedisMemoryConfig.setKeyPrefix(keyPrefix);
            myRedisMemoryConfig.setTimeToLiveSeconds(timeToLiveSeconds);
            myRedisMemoryConfig.setClearTaskCron(clearTaskCron);
            myRedisMemoryConfig.setMaxConvCountPerClearScan(maxConvCountPerClearScan);
            myRedisMemoryConfig.setMaxConvCountLocalCache(maxConvCountLocalCache);
            return myRedisMemoryConfig;
        }
    }
}
